#ifndef CONFIG_H_
#define CONFIG_H_

#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <modbus/modbus.h>
#include "constant.h"
#include "vector.h"
#include "list.h"
#include "hash.h"

typedef struct {
    period_e period;
    uint16_t delay;
} interval_t;

typedef struct {
    data_catalog_e catalog;
    interval_t read;
    interval_t pub;

    //下次计划启动时间，当此时间在当前时间以前，表示应该运行
    //在运行时计算下次启动时间，依次循环
    //要迭代完全部data_catalog再进入下一轮，防止由于某个任务执行时间过长导致其他任务未触发
    time_t _next_sched;
} data_catalog_t;

data_catalog_t *data_catalog_new();

void data_catalog_free(data_catalog_t *catalog);

typedef int obj_id;

typedef struct {
    obj_id id;
    char name[80];
} object_t;

typedef struct {
    object_t super;

    protocol_e protocol;

    char u0[32], i0[32]; //电压电流量程
    char ubb[32], ibb[32]; //电压电流变比
    char u_decimal[32], i_decimal[32], p_decimal[32];

    vector_t/*thing_model_t*/ thing_model[seg_max];

    char product_key[64];
    char product_secret[64];

    char vendor[40]; //制造商
    char model[40]; //型号

    //多个相似产品对应同一个物模型，通过偏移量确定寄存器偏移顺序
    _Bool is_shift;
    uint16_t di_shift, do_shift, ai_shift, ao_shift;

    //需要加载物模型，已经加载物模型
    _Bool _loading, _loaded;
} product_t;

product_t *product_new();

void product_free(product_t *product);

typedef struct {
    object_t super;

    obj_id product;
    segment_e segment;
    uint16_t offset;
    char metric[32];

    data_catalog_e catalog;
    data_type_e data_type;
    _Bool swap_byte, swap_word, swap_dword;
    writable_e writable;

    value_type_e value_type;

    //智能电表使用的识别符
    uint32_t data_identifier;

    //参与电流和电压系数处理方式
    _Bool mul_u, mul_i;
    //标度化值：y = x / pow(10, u_decimal|i_decimal|p_decimal)
    //归一化值：y = x * [i0 * ibb] * [u0 * ubb] / scale + adjust

    //标度化值处理 y = x / pow(10, decimal)
    int digit, decimal;

    //归一化值处理 y = x / scale + adjust
    double scale, adjust;

    //最大最小界限值
    double valid_max, valid_min;

    uint16_t time_tag;
    time_type_e time_type;

    _Bool _auto;
    _Bool _start;
    _Bool _skip;
} thing_model_t;

thing_model_t *thing_model_new();

void thing_model_free(thing_model_t *model);

uint16_t thing_model_tag_id(thing_model_t *model);

typedef struct {
    _Bool initialized; //已经初始化
    uint16_t successful, failed; //此轮循环的成功和失败次数，每一轮循环清零
    uint16_t retries; //标记为失败后的重试次数，一旦有任何一次成功，此标志清零
    uint16_t total_messages;//发送报文总数
    time_t last_active; //最后一次活动
    time_t next_sched; //下次计划时间
    void *data; //自定义状态
} comm_stat_t;

typedef struct {
    object_t super;

    obj_id product;
    obj_id channel;

    uint16_t slave_id;
    uint8_t meter_addr[6];

    int u0, i0; //电压电流量程
    int ubb, ibb; //电压电流变比
    int8_t u_decimal, i_decimal, p_decimal;
    uint8_t shift_idx;

    char device_key[64];
    char device_secret[64];

    product_t *_product; //指向产品的引用
    comm_stat_t _stat;
    hash_t *values;
    vector_t thing_value[seg_max]; //用于保存最新值value_t
} device_t;

device_t *device_new();

void device_free(device_t *device);

typedef struct {
    char device[32];
    int baud;
    int parity;
    int data_bits;
    int stop_bits;
    int gpio;
} serial_params_t;

typedef struct {
    char addr[80];
    uint16_t port;
} tcpip_params_t;

typedef struct {
    object_t super;

    channel_type_e type;
    protocol_e protocol;

    serial_params_t serial;
    tcpip_params_t tcpip;
    int timeout;

    vector_t devices;

    int fd;
    modbus_t *modbus;

    _Bool _debug;
    //当通道下所有设备都全部失败，标记该通道有问题，断开后重新连接
    comm_stat_t _stat;
} channel_t;

channel_t *channel_new();

void channel_free(channel_t *channel);

typedef struct {
    payload_format_e fmt;
    char topic[128];
    _Bool is_subscribe;
} topic_t;

typedef struct {
    object_t super;

    uint16_t rtu;
    //判断初次进入
    uint16_t times;
    upload_type_e type;
    payload_format_e payload;

    tcpip_params_t remote_address;
    _Bool ssl;

    uint32_t timeout;
    uint32_t heartbeat;

    char username[64];
    char password[64];
    char client_id[64];

    char product_key[64];
    char device_key[64];
    char device_secret[64];

    vector_t/*topic_t*/ topics;

    comm_stat_t _stat;
} uplink_t;

typedef struct {
    char local_address[16];
    uplink_t *default_uplink;
    vector_t/*uplink_t*/ uplinks;
    vector_t/*channel_t*/ channels;
    vector_t/*sys_info_t*/ sysinfos;
    vector_t/*product_t*/ products;
    vector_t/*data_catalog_t*/ catalogs;
} seqiot_t;

seqiot_t *seqiot_new();

void seqiot_free(seqiot_t *seqiot);

#endif /* CONFIG_H_ */
